
package guice.boot.archive.container.pipeline;

import com.google.inject.Singleton;
import guice.boot.archive.common.log.Logger;
import guice.boot.archive.common.log.LoggerFactory;
import guice.boot.archive.container.service.ContainerHolder;
import guice.boot.archive.exception.ArkRuntimeException;
import guice.boot.archive.spi.pipeline.Pipeline;
import guice.boot.archive.spi.pipeline.PipelineContext;
import guice.boot.archive.spi.pipeline.PipelineStage;

import java.util.ArrayList;
import java.util.List;

@Singleton
public class StandardPipeline implements Pipeline {

    private static final Logger LOGGER = LoggerFactory.getDefaultLogger();
    private List<PipelineStage> stages = new ArrayList<>();

    public StandardPipeline() {
        initializePipeline();
    }

    private void initializePipeline() {
        addPipelineStage(
                ContainerHolder.getContainer().getService(HandleArchiveStage.class))
                .addPipelineStage(
                        ContainerHolder.getContainer().getService(RegisterServiceStage.class))
                .addPipelineStage(
                        ContainerHolder.getContainer().getService(ExtensionLoaderStage.class))
                .addPipelineStage(
                        ContainerHolder.getContainer().getService(DeployPluginStage.class))
                .addPipelineStage(
                        ContainerHolder.getContainer().getService(DeployBizStage.class))
                .addPipelineStage(
                        ContainerHolder.getContainer().getService(FinishStartupStage.class));
    }

    @Override
    public Pipeline addPipelineStage(PipelineStage pipelineStage) {
        stages.add(pipelineStage);
        return this;
    }

    @Override
    public void process(PipelineContext pipelineContext) throws ArkRuntimeException {
        for (PipelineStage pipelineStage : stages) {
            try {
                LOGGER.info(String.format("Start to process pipeline stage: %s", pipelineStage
                        .getClass().getName()));
                pipelineStage.process(pipelineContext);
                LOGGER.info(String.format("Finish to process pipeline stage: %s", pipelineStage
                        .getClass().getName()));
            } catch (Throwable e) {
                LOGGER.error(String.format("Process pipeline stage fail: %s", pipelineStage
                        .getClass().getName()), e);
                throw new ArkRuntimeException(e);
            }
        }
    }
}